#ifndef __INJECT
#define __INJECT
#include<vector>
#include "type.h"
#include "simbox.h"
#include "particles.h"
#include "events.h"
#include "physicalconstants.h"


/// 粒子入射枪,可以指定粒子种类,和入射位置,目前尽采用四方形束流,以后会有更多的如高斯型等.
class __Injector{
    public:
        int id;
        /// 入射粒子种类
        int species;
        /// 枪的中心位置
        __Vect2<int> position;
        /// GPS of gun
        __Vect2<double> gps;
        /// 束流速度
        __Vect3<double> velocity;
        /// 初始粒子的id
        static long& pid;
        /// 束流横向宽度
        double length;
        /// 重复次数,目前美柚用
        int repetion;
        /// 束流,粒子数/立方米/s
        double flux;
        /// 网格的x,y方向的宽度
        double dx, dy;
        /// 束流横向所占网格数
        int diameter;
        /// 单个粒子能量,j
        double energy;
        /// 粒子电荷
        double charge;
        /// 粒子质量
        double mass;
        /// 入射宏粒子总数
        long total;
        /// 粒子的gamma因子
        double lorentz_gamma;
        __Injector(int id, int species, const double& charge, const double& mass, __Vect2<int> position, \
                __Vect3<double>& velocity, const long& total, \
                const double length, const double flux, const double& dx, const \
                double& dy):id(id), species(species), charge(charge), mass(mass)\
        , velocity(velocity), position(position), total(total), length(length), \
                            flux(flux), \
                            dx(dx), dy(dy){ 
            diameter = length / 2.0 / dx; 
            lorentz_gamma = 1.0 / sqrt(1.0 - velocity * velocity / c_light_speed / c_light_speed);
            energy = lorentz_gamma * mc2;
        }
        ~__Injector(){}
        /// 入射粒子加入到box中
        void trigger(__Simbox& mybox);
        void destroy();
};




void __Injector::trigger(__Simbox& mybox)
{

    if(total <= 0)
    {
        return;
    }
    int ptcls_num  = 100;//mybox.delta_t * flux * length / weight;
    //cout<<"pnu "<<mybox.delta_t<<" flu "<<flux<<" len "<<length<<" wt "<<weight<<endl;
    double len_x = velocity.member[0] * mybox.delta_t;
    double ybx = length / len_x;
    int nx = sqrt(ptcls_num / ybx);
    int ny = nx * ybx;
    if(nx <= 1)
    {
        nx = 1;
        ny = ptcls_num / nx;
    }
    //cout<<"ybx, nx, ny "<<ybx<<"\t"<<nx<<"\t"<<ny<<endl;
    double ddx = len_x / nx, ddy = length / ny;
    int weight = flux * length * len_x / ptcls_num;
    __Vect2<double> pos(position.member[0], position.member[1]);
    //cout<<"pos "<<pos<<endl;
    __Vect2<double> particle_position0 = pos * dx;
    particle_position0.member[1] -= length * 0.5;
    int posi, posj;
    for(int i = 0; i < ptcls_num; i ++)
    {
        __Vect2<double> particle_position = particle_position0; // + offset * (i * 1.0 / ptcls_num);
        particle_position.member[0] += len_x * random_generator();
        particle_position.member[1] += length * random_generator();
        posi = (particle_position.member[0] - mybox.xymin.member[0]) / dx;
        posj = (particle_position.member[1] - mybox.xymin.member[1]) / dy;
        //cout<<"i, j "<<posi<<"\t"<<posj<<" "<<particle_position<<endl;
        //cout<<"velocity "<<velocity<<endl;
        //cout<<"before creating "<<pid<<endl;
        __Ptcls myptcl(particle_position, velocity, weight, energy, \
                charge);
        //cout<<"after creating "<<pid<<"\t total_id "<<myptcl.total_id<<endl;
        myptcl.mass = mass;
        myptcl.species = species;
        myptcl.lorentz_gamma = lorentz_gamma;
        //myptcl.total_id = pid;
        //cout<<" particle id "<<myptcl.id<<endl;
        //getchar();
        mybox.cellgroup.member[posi][posj].push(myptcl);
        total --;
        if(total <= 0)
        {
            return;
        }
    }

    /***
    for(int i = 0; i < nx; i ++)
    {
        for(int j = 0; j < ny; j ++)
        {
            __Vect2<double> particle_position = particle_position0; // + offset * (i * 1.0 / ptcls_num);
            particle_position.member[0] += i * ddx;
            particle_position.member[1] += j * ddy;
            posi = (particle_position.member[0] - mybox.xymin.member[0]) / dx;
            posj = (particle_position.member[1] - mybox.xymin.member[1]) / dy;
            //cout<<"ek "<<energy<<endl;
            //cout<<"i, j "<<posi<<"\t"<<posj<<" "<<particle_position<<endl;
            //cout<<"velocity "<<velocity<<endl;
            __Ptcls myptcl(pid, particle_position, velocity, weight, energy, \
                    charge);
            myptcl.mass = mass;
            myptcl.species = species;
            mybox.cellgroup.member[posi][posj].push(myptcl);
            pid ++;
        }
    }

    ***/

}

/***
void __Injector::destroy()
{
    ~__Injector();
}
***/
        
#endif
